package com.it.alg;

import java.util.Map;

import com.it.io.IOSequence;
import com.it.io.IOSequenceFactory;

public class DupAlgorithmReplImpl<S, E> extends DupAlgorithmTemplate {

	public DupAlgorithmReplImpl(ConfImpl<S, E> conf) {
		super(conf);
	}

	@Override
	protected <S, E> void replace(IOSequenceFactory<S, E> ioSequenceFactory, int repeatCount, E value, Stack<S, E> stack) {
		ConfImpl confImpl = (ConfImpl) conf;
		S s = (S) confImpl.map.get(value);
		if (s != null) {
			IOSequence<S, E> ioSequence = ioSequenceFactory.getIOSequence();
			ioSequence.initInput(s);
			while (ioSequence.hasInput()) {
				E e = ioSequence.input();
				this.push(ioSequenceFactory, stack, e);
			}
		}
	}
	
	@Override
	protected <S, E> String getStepRemark(IOSequenceFactory<S, E> ioSequenceFactory, int repeatCount, E value,
			Stack<S, E> stack, String separator) {
		ConfImpl confImpl = (ConfImpl) conf;
		S s = (S) confImpl.map.get(value);
		if (s != null) {
			StringBuilder buf = new StringBuilder();
			buf.append(value);
			for (int i = 1; i < repeatCount; i++) {
				buf.append(separator).append(value);
			}
			buf.append(" is replaced by ");
			
			IOSequence<S, E> ioSequence = ioSequenceFactory.getIOSequence();
			ioSequence.initInput(s);
			boolean flag = false;
			while (ioSequence.hasInput()) {
				E e = ioSequence.input();
				if (flag) {
					buf.append(separator);
				} else {
					flag = true;
				}
				buf.append(e);
			}
			return buf.toString();
		} else {
			return "";
		}
	}

	public static class ConfImpl<S, E> extends Conf {
		
		Map<E, S> map;
		
		public ConfImpl(Map<E, S> map) {
			this(map, new Conf() {});
		}
		
		public ConfImpl(Map<E, S> map, Conf conf) {
			this.map = map;
			this.repeatNum = conf.repeatNum;
			this.needStackChange = conf.needStackChange;
			this.needStepResult = conf.needStepResult;
			this.out = conf.out;
			this.separator = conf.separator;
		}
	}

}
